package com.xbongbong.process.operate;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.PaasProcessDataEntity;
import com.xbongbong.paas.domain.entity.PaasProcessNodeTaskEntity;
import com.xbongbong.paas.domain.entity.PaasProcessRichTextEntity;
import com.xbongbong.paas.domain.entity.PaasProcessTaskEntity;
import com.xbongbong.paas.domain.entity.PaasProcessTemplateEntity;
import com.xbongbong.paas.domain.entity.ext.ConditionsEntityExt;
import com.xbongbong.paas.domain.entity.ext.OptionalRangeEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasProcessNodeTaskEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasProcessTemplateNodeEntityExt;
import com.xbongbong.paas.enums.ApproverDeduplicationEnum;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.NodeTypeEnum;
import com.xbongbong.paas.enums.ProcessEmptyApproverTypeEnum;
import com.xbongbong.paas.enums.ProcessTypeEnum;
import com.xbongbong.paas.enums.TaskTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.ItemPoJo;
import com.xbongbong.paas.help.CompareValueByConditionHelp;
import com.xbongbong.paas.help.FormDataHelp;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.model.PaasProcessDataModel;
import com.xbongbong.paas.model.PaasProcessNodeTaskModel;
import com.xbongbong.paas.model.PaasProcessRelatedDataModel;
import com.xbongbong.paas.model.PaasProcessTaskModel;
import com.xbongbong.paas.model.PaasProcessTemplateModel;
import com.xbongbong.paas.model.PaasProcessTemplateNodeModel;
import com.xbongbong.paas.pojo.FormTitlePoJo;
import com.xbongbong.paas.pojo.dto.ProcessConditionValidDTO;
import com.xbongbong.paas.pojo.dto.ProcessDataAddDTO;
import com.xbongbong.paas.pojo.dto.ProcessNodeTaskAddBatchDTO;
import com.xbongbong.paas.pojo.dto.ProcessNodeTaskAddDTO;
import com.xbongbong.paas.pojo.dto.ProcessTaskAddDTO;
import com.xbongbong.paas.pojo.dto.StartProcessDTO;
import com.xbongbong.paas.pojo.vo.ProcessDataAddVO;
import com.xbongbong.paas.pojo.vo.ProcessTaskAddVO;
import com.xbongbong.paas.pojo.vo.StartProcessVO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CloneUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.paas.util.FormDataUtil;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.workrecord.enums.WorkrecordResultEnum;
import com.xbongbong.pro.message.pojo.PushRefTypePojo;
import com.xbongbong.pro.process.pojo.dto.WorkrecordInstanceDTO;
import com.xbongbong.pro.service.dingtalk.WorkflowDingtalkService;
import com.xbongbong.pro.user.pojo.ReturnUserAndDepartmentPojo;
import com.xbongbong.process.ProcessOperateHelp;
import com.xbongbong.process.data.PaasProcessDataServiceImpl;
import com.xbongbong.process.ding.DingtalkWorkrecordService;
import com.xbongbong.process.task.NodeTaskListStartProcessServiceImpl;
import com.xbongbong.process.task.PaasProcessTaskService;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.domain.entity.WorkOrderExplainEntity;
import com.xbongbong.saas.domain.entity.WorkOrderFormEntity;
import com.xbongbong.saas.enums.SignTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.model.PaasProcessRichTextModel;
import com.xbongbong.saas.model.WorkOrderExplainModel;
import com.xbongbong.saas.model.WorkOrderFormModel;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.DepartmentModel;
import com.xbongbong.sys.model.UserModel;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

/**
 * @author: wufeng
 * @date: 2018/11/20 9:53
 * @desrcption: 流程任务操作
 */
@Service("paasProcessOperateService")
public class PaasProcessOperateServiceImpl implements PaasProcessOperateService {

    private static final Logger LOG = LoggerFactory.getLogger(PaasProcessOperateServiceImpl.class);

    @Resource
    private PaasProcessTaskService paasProcessTaskService;
    @Resource
    private PaasProcessTemplateNodeModel paasProcessTemplateNodeModel;
    @Resource
    private PaasProcessDataServiceImpl paasProcessDataService;
    @Resource
    private NodeTaskListStartProcessServiceImpl nodeTaskListStartProcessService;
    @Resource
    private PaasProcessNodeTaskModel paasProcessNodeTaskModel;
    @Resource
    private DingtalkWorkrecordService dingtalkWorkrecordService;
    @Resource
    private WorkflowDingtalkService workflowDingtalkService;
    @Resource
    private WorkOrderFormModel workOrderFormModel;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private CompareValueByConditionHelp compareValueByConditionHelp;
    @Resource
    private UserModel userModel;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private WorkOrderExplainModel workOrderExplainModel;
    @Resource
    private DepartmentModel departmentModel;
    @Resource
    private ProcessOperateHelp processOperateHelp;
    @Resource
    private PaasProcessTemplateModel paasProcessTemplateModel;
    @Resource
    private PaasProcessDataModel paasProcessDataModel;
    @Resource
    private PaasProcessTaskModel paasProcessTaskModel;
    @Resource
    private FormDataHelp formDataHelp;
    @Resource
    private PaasProcessRelatedDataModel paasProcessRelatedDataModel;
    @Resource
    private PaasProcessRichTextModel paasProcessRichTextModel;

    @Override
    public StartProcessVO dingStartProcess(StartProcessDTO startProcessDTO) throws XbbException {
        StartProcessVO startProcessVO = new StartProcessVO();
        String corpid = startProcessDTO.getCorpid();
        try {
            ProcessDataAddDTO processDataAddDTO = new ProcessDataAddDTO();
            BeanUtil.copyProperties(startProcessDTO, processDataAddDTO);

            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put("del", DelEnum.NORMAL.getDel());
            params.put("corpid", corpid);
            params.put("templateId", startProcessDTO.getTemplateId());
            params.put("type", NodeTypeEnum.START_PROCESS_NODE.getNodeType());
            // 查找开始节点
            List<PaasProcessTemplateNodeEntityExt> startNodeList = paasProcessTemplateNodeModel.list(params);
            if (startNodeList == null || startNodeList.size() == 0) {
                startProcessVO.setNoApprovalRequired(1);
                return startProcessVO;
            }
            PaasProcessTemplateNodeEntityExt templateNodeEntityExt = startNodeList.get(0);

//            boolean isNeedApprove = isNeedApprove(templateNodeEntityExt, processDataAddDTO);
//            if (!isNeedApprove) {
//                startProcessVO.setNoApprovalRequired(1);
//                return startProcessVO;
//            }

            // 主任务生成
            ProcessTaskAddDTO processTaskAddDTO = new ProcessTaskAddDTO();
            BeanUtil.copyProperties(startProcessDTO, processTaskAddDTO);
            ProcessTaskAddVO processTaskAddVO = paasProcessTaskService.createProcessTask(processTaskAddDTO);
            if(processTaskAddVO == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.START_PROCESS_ERROR);
            }
            Long taskId = processTaskAddVO.getTaskId();
            processDataAddDTO.setTaskId(taskId);
            //提取并保存富文本数据
            saveProcessRichText(processDataAddDTO, FormDataUtil.removeRichText(processDataAddDTO.getData()));
            // 保存流程数据
            ProcessDataAddVO processDataAddVO = paasProcessDataService.add(processDataAddDTO);
            startProcessVO = createNodeTask(startProcessDTO, templateNodeEntityExt, processDataAddDTO);
            // 第一个节点自动拒绝
            if (Objects.equals(startProcessVO.getNoApprovalRequired(), BasicConstant.TWO)) {
                // 更新流程状态
                PaasProcessTaskEntity paasProcessTaskEntity = new PaasProcessTaskEntity();
                paasProcessTaskEntity.setCorpid(corpid);
                paasProcessTaskEntity.setId(taskId);
                paasProcessTaskEntity.setFlowStatus(FlowStatusEnum.REJECT.getType());
                paasProcessTaskModel.update(paasProcessTaskEntity);
                // 更新数据状态
                PaasProcessDataEntity paasProcessDataEntity = new PaasProcessDataEntity();
                paasProcessDataEntity.setCorpid(corpid);
                paasProcessDataEntity.setId(processDataAddVO.getProcessDataId());
                paasProcessDataEntity.setFlowStatus(FlowStatusEnum.REJECT.getType());
                paasProcessDataModel.update(paasProcessDataEntity);
                paasProcessRelatedDataModel.updateFlowStatusByTaskId(taskId, corpid, FlowStatusEnum.REJECT.getType());
                if (Objects.nonNull(startProcessDTO.getFormDataId()) && startProcessDTO.getFormDataId() > 0L) {
                    paasProcessDataEntity.setFormDataId(startProcessDTO.getFormDataId());
                    paasProcessDataEntity.setSaasMark(startProcessDTO.getSaasMark());
                    paasProcessDataEntity.setBusinessType(startProcessDTO.getBusinessType());
                    formDataHelp.updateFormDataStatus(paasProcessDataEntity, FlowStatusEnum.PASS.getType());
                }
            } if (Objects.equals(startProcessVO.getNoApprovalRequired(), BasicConstant.ONE)) {
                // 更新流程状态
                PaasProcessTaskEntity paasProcessTaskEntity = new PaasProcessTaskEntity();
                paasProcessTaskEntity.setCorpid(corpid);
                paasProcessTaskEntity.setId(taskId);
                paasProcessTaskEntity.setFlowStatus(FlowStatusEnum.PASS.getType());
                paasProcessTaskModel.update(paasProcessTaskEntity);
                // 更新数据状态
                PaasProcessDataEntity paasProcessDataEntity = new PaasProcessDataEntity();
                paasProcessDataEntity.setCorpid(corpid);
                paasProcessDataEntity.setId(processDataAddVO.getProcessDataId());
                paasProcessDataEntity.setFlowStatus(FlowStatusEnum.PASS.getType());
                paasProcessDataModel.update(paasProcessDataEntity);
                paasProcessRelatedDataModel.updateFlowStatusByTaskId(taskId, corpid, FlowStatusEnum.PASS.getType());
                //自动通过更新钉钉实例为审批通过
                PaasProcessTaskEntity newPaasProcessTaskEntity = paasProcessTaskModel.getByKey(Math.toIntExact(taskId), corpid);
                String dingtalkProcessInstanceId = newPaasProcessTaskEntity.getDingtalkProcessInstanceId();
                if (StringUtil.isEmpty(dingtalkProcessInstanceId)){
                    workflowDingtalkService.updateDingtalkInstance(startProcessDTO.getCorpid(), newPaasProcessTaskEntity.getDingtalkProcessInstanceId(), WorkrecordResultEnum.AGREE);
                }
            }
            startProcessVO.setTaskId(taskId);
        } catch (XbbException e){
            throw e;
        } catch (Exception e) {
            LOG.error("paasProcessOperate开始流程创建主流程任务报错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return startProcessVO;
    }

    @Override
    public StartProcessVO createNodeTask(StartProcessDTO startProcessDTO, PaasProcessTemplateNodeEntityExt templateNodeEntityExt, ProcessDataAddDTO processDataAddDTO) throws XbbException {
        // 生成开始节点任务
        createStartNodeTask(startProcessDTO, templateNodeEntityExt, processDataAddDTO.getTaskId());
        return deliverToNextNode(templateNodeEntityExt, processDataAddDTO);
    }

    @Override
    public void createStartNodeTask(StartProcessDTO startProcessDTO, PaasProcessTemplateNodeEntityExt templateNodeEntityExt, Long taskId) throws XbbException {
        long now = DateUtil.getInt();
        PaasProcessNodeTaskEntity paasProcessNodeTaskEntity = new PaasProcessNodeTaskEntity();
        BeanUtil.copyProperties(startProcessDTO, paasProcessNodeTaskEntity);
        paasProcessNodeTaskEntity.setTaskId(taskId);
        paasProcessNodeTaskEntity.setTemplateNodeId(templateNodeEntityExt.getId());
        paasProcessNodeTaskEntity.setNodeType(NodeTypeEnum.START_PROCESS_NODE.getNodeType());
        paasProcessNodeTaskEntity.setTaskType(TaskTypeEnum.COMMIT.getType());
        paasProcessNodeTaskEntity.setUserId(startProcessDTO.getCreatorId());
        paasProcessNodeTaskEntity.setCreatorId(startProcessDTO.getCreatorId());
        paasProcessNodeTaskEntity.setSignType(templateNodeEntityExt.getSignType());
        paasProcessNodeTaskEntity.setOpinion("");
        paasProcessNodeTaskEntity.setAttachment(JSONObject.toJSONString(new ArrayList<>()));
        paasProcessNodeTaskEntity.setImages(JSONObject.toJSONString(new ArrayList<>()));
        paasProcessNodeTaskEntity.setRevokeUserId("");
        paasProcessNodeTaskEntity.setActivationNode(0L);
        paasProcessNodeTaskEntity.setBackspaceNode(0L);
        paasProcessNodeTaskEntity.setTransferUserId("");
        paasProcessNodeTaskEntity.setAddTime(now);
        paasProcessNodeTaskEntity.setUpdateTime(now);
        paasProcessNodeTaskEntity.setLastNodeId(0L);
        paasProcessNodeTaskModel.insert(paasProcessNodeTaskEntity);

        // 发送待办消息
        try {
            sendDingtalkWorkrecord(startProcessDTO, taskId, paasProcessNodeTaskEntity.getId());
        } catch (Exception e){
            LOG.error("dingtalkWorkrecordService.createWorkrecordInstance error: ", e);
        }
    }

    @Override
    public StartProcessVO deliverToNextNode(PaasProcessTemplateNodeEntityExt templateNodeEntityExt, ProcessDataAddDTO processDataAddDTO) throws XbbException {
        StartProcessVO startProcessVO = new StartProcessVO();
        String lastNodeId = templateNodeEntityExt.getUid();
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put("corpid", templateNodeEntityExt.getCorpid());
        params.put("prevId", lastNodeId);
        params.put("formId", templateNodeEntityExt.getFormId());
        params.put("menuId", templateNodeEntityExt.getMenuId());
        params.put("orderByStr", " priority " + SortOrder.ASC);
        params.put("del", 0);
        params.put("templateId", templateNodeEntityExt.getTemplateId());
        List<PaasProcessTemplateNodeEntityExt> nextNodeList = paasProcessTemplateNodeModel.list(params);
        if (nextNodeList.isEmpty()) {
            String wrapperId = templateNodeEntityExt.getWrapperId();
            // wrapper外面包一层wrapper的情况
            startProcessVO = deliverToNextNode(templateNodeEntityExt, processDataAddDTO, startProcessVO, params, wrapperId);
        } else {
            // 当前为wrapper节点时，子节点应该去判断条件节点
            if (Objects.equals(templateNodeEntityExt.getType(), NodeTypeEnum.CONDITION_WRAPPER_PROCESS_NODE.getNodeType())) {
                List<PaasProcessTemplateNodeEntityExt> nextConditionNodeList = new ArrayList<>();
                nextNodeList.forEach(item -> {
                    if (Objects.equals(item.getType(), NodeTypeEnum.CONDITION_PROCESS_NODE.getNodeType())) {
                        nextConditionNodeList.add(item);
                    }
                });
                // 判断条件节点任务是否符合 返回符合条件的条件节点
                PaasProcessTemplateNodeEntityExt nextConditionNode = conditionIsMet(nextConditionNodeList, processDataAddDTO);
                if (nextConditionNode == null) {
                    // updateProcess(processDataAddDTO);
                } else {
                    // 继续向下推进任务
                    startProcessVO = deliverToNextNode(nextConditionNode, processDataAddDTO);
                }
            } else {
                // 其他类型节点时，只有一个子节点
                if (nextNodeList.size() > 1) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
                }
                PaasProcessTemplateNodeEntityExt nextNode = nextNodeList.get(0);
                if (Objects.equals(nextNode.getType(), NodeTypeEnum.CONDITION_WRAPPER_PROCESS_NODE.getNodeType())) {
                    startProcessVO = deliverToNextNode(nextNode, processDataAddDTO);
                } else {
                    startProcessVO = createNodeTask(nextNode, processDataAddDTO, templateNodeEntityExt.getId());
                }
            }
        }
        return startProcessVO;
    }

    private StartProcessVO deliverToNextNode(PaasProcessTemplateNodeEntityExt templateNodeEntityExt, ProcessDataAddDTO processDataAddDTO, StartProcessVO startProcessVO, Map<String, Object> params, String wrapperId) throws XbbException {
        if (StringUtil.isEmpty(wrapperId)) {
            // updateProcess(processDataAddDTO);
        } else {
            // 如果有wrapperId说明分支块走完，查找下一个非分支节点的子节点
            params.put("prevId", wrapperId);
            params.put("typeNotIn", Collections.singletonList(NodeTypeEnum.CONDITION_PROCESS_NODE.getNodeType()));
            List<PaasProcessTemplateNodeEntityExt> nodeList = paasProcessTemplateNodeModel.list(params);
            if (nodeList.isEmpty()) {
                params.remove("prevId");
                params.remove("typeNotIn");
                params.put("uid", wrapperId);
                List<PaasProcessTemplateNodeEntityExt> wapperNodeList = paasProcessTemplateNodeModel.list(params);
                params.remove("uid");
                if (!wapperNodeList.isEmpty()) {
                    wrapperId = wapperNodeList.get(0).getWrapperId();
                    if (!StringUtil.isEmpty(wrapperId)) {
                        startProcessVO = deliverToNextNode(wapperNodeList.get(0),processDataAddDTO, startProcessVO, params, wrapperId);
                    }
                }
            } else {
                PaasProcessTemplateNodeEntityExt nextNode = nodeList.get(0);
                if (Objects.equals(nextNode.getType(), NodeTypeEnum.CONDITION_WRAPPER_PROCESS_NODE.getNodeType())) {
                    startProcessVO = deliverToNextNode(nextNode, processDataAddDTO);
                } else {
                    startProcessVO = createNodeTask(nextNode, processDataAddDTO, templateNodeEntityExt.getId());
                }
            }
        }
        return startProcessVO;
    }

    /*@Override
    public boolean isNeedApprove(PaasProcessTemplateNodeEntityExt templateNodeEntityExt, ProcessDataAddDTO processDataAddDTO) throws XbbException {
        String lastNodeId = templateNodeEntityExt.getUid();
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put("corpid", templateNodeEntityExt.getCorpid());
        params.put("prevId", lastNodeId);
        params.put("formId", templateNodeEntityExt.getFormId());
        params.put("orderByStr", " priority " + SortOrder.ASC);
        params.put("del", 0);
        params.put("templateId", templateNodeEntityExt.getTemplateId());
        params.put("menuId", templateNodeEntityExt.getMenuId());
        List<PaasProcessTemplateNodeEntityExt> nextNodeList = paasProcessTemplateNodeModel.list(params);
        PaasProcessTemplateEntity processTemplateEntity = paasProcessTemplateModel.getByKey(templateNodeEntityExt.getTemplateId().intValue(), processDataAddDTO.getCorpid());
        Integer emptyApproverType = processTemplateEntity != null ? processTemplateEntity.getEmptyApproverType() : ProcessEmptyApproverTypeEnum.ADMIN_TRANSFER.getValue();
        if (nextNodeList.isEmpty()) {
            String wrapperId = templateNodeEntityExt.getWrapperId();
            // wrapper外面包一层wrapper的情况
            return isNeedApprove(processDataAddDTO, params, wrapperId, emptyApproverType);
        } else {
            // 当前为wrapper节点时，子节点应该去判断条件节点
            if (Objects.equals(templateNodeEntityExt.getType(), NodeTypeEnum.CONDITION_WRAPPER_PROCESS_NODE.getNodeType())) {
                List<PaasProcessTemplateNodeEntityExt> nextConditionNodeList = new ArrayList<>();
                nextNodeList.forEach(item -> {
                    if (Objects.equals(item.getType(), NodeTypeEnum.CONDITION_PROCESS_NODE.getNodeType())) {
                        nextConditionNodeList.add(item);
                    }
                });
                // 判断条件节点任务是否符合 返回符合条件的条件节点
                PaasProcessTemplateNodeEntityExt nextConditionNode = conditionIsMet(nextConditionNodeList, processDataAddDTO);
                if (nextConditionNode == null) {
                    return false;
                } else {
                    // 继续向下推进任务
                    return isNeedApprove(nextConditionNode, processDataAddDTO);
                }
            } else {
                // 其他类型节点时，只有一个子节点
                if (nextNodeList.size() > 1) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
                }
                PaasProcessTemplateNodeEntityExt nextNode = nextNodeList.get(0);
                if (Objects.equals(nextNode.getType(), NodeTypeEnum.CONDITION_WRAPPER_PROCESS_NODE.getNodeType())) {
                    return isNeedApprove(nextNode, processDataAddDTO);
                } else {
                    if (Objects.equals(nextNode.getType(), NodeTypeEnum.CC_PROCESS_NODE.getNodeType())) {
                        return isNeedApprove(nextNode, processDataAddDTO);
                    } else {
                        List<OptionalRangeEntity> userList = nextNode.getMainUserList();
                        // 生成负责人任务
                        ProcessConditionValidDTO processConditionValidDTO = new ProcessConditionValidDTO();
                        BeanUtil.copyProperties(processDataAddDTO, processConditionValidDTO);
                        List<ProcessNodeTaskAddDTO> userNodeTaskList = nodeTaskListStartProcessService.getNodeTaskList(userList, processConditionValidDTO, nextNode, TaskTypeEnum.UNTREATED.getType());
                        if (userNodeTaskList.isEmpty()) {
                            if (Objects.equals(emptyApproverType, ProcessEmptyApproverTypeEnum.AUTO_PAAS.getValue())) {
                                return isNeedApprove(nextNode, processDataAddDTO);
                            } else {
                                return true;
                            }
                        } else {
                            return true;
                        }
                    }
                }
            }
        }
    }

    private boolean isNeedApprove(ProcessDataAddDTO processDataAddDTO, Map<String, Object> params, String wrapperId, Integer emptyApproverType) throws XbbException {
        if (StringUtil.isEmpty(wrapperId)) {
            return false;
        } else {
            // 如果有wrapperId说明分支块走完，查找下一个非分支节点的子节点
            params.put("prevId", wrapperId);
            params.put("typeNotIn", Collections.singletonList(NodeTypeEnum.CONDITION_PROCESS_NODE.getNodeType()));
            List<PaasProcessTemplateNodeEntityExt> nodeList = paasProcessTemplateNodeModel.list(params);
            if (nodeList.isEmpty()) {
                params.remove("prevId");
                params.remove("typeNotIn");
                params.put("uid", wrapperId);
                List<PaasProcessTemplateNodeEntityExt> wapperNodeList = paasProcessTemplateNodeModel.list(params);
                params.remove("uid");
                if (!wapperNodeList.isEmpty()) {
                    wrapperId = wapperNodeList.get(0).getWrapperId();
                    if (!StringUtil.isEmpty(wrapperId)) {
                        return isNeedApprove(processDataAddDTO, params, wrapperId, emptyApproverType);
                    } else {
                        return false;
                    }
                } else {
                    return false;
                }
            } else {
                PaasProcessTemplateNodeEntityExt nextNode = nodeList.get(0);
                if (Objects.equals(nextNode.getType(), NodeTypeEnum.CONDITION_WRAPPER_PROCESS_NODE.getNodeType())
                        || Objects.equals(nextNode.getType(), NodeTypeEnum.CC_PROCESS_NODE.getNodeType())) {
                    return isNeedApprove(nextNode, processDataAddDTO);
                } else {
                    List<OptionalRangeEntity> userList = nextNode.getMainUserList();
                    // 生成负责人任务
                    ProcessConditionValidDTO processConditionValidDTO = new ProcessConditionValidDTO();
                    BeanUtil.copyProperties(processDataAddDTO, processConditionValidDTO);
                    List<ProcessNodeTaskAddDTO> userNodeTaskList = nodeTaskListStartProcessService.getNodeTaskList(userList, processConditionValidDTO, nextNode, TaskTypeEnum.UNTREATED.getType());
                    if (userNodeTaskList.isEmpty()) {
                        if (Objects.equals(emptyApproverType, ProcessEmptyApproverTypeEnum.AUTO_PAAS.getValue())) {
                            return isNeedApprove(nextNode, processDataAddDTO);
                        } else {
                            return true;
                        }
                    } else {
                        return true;
                    }
                }
            }
        }
    }*/

    private PaasProcessTemplateNodeEntityExt conditionIsMet(List<PaasProcessTemplateNodeEntityExt> nextConditionNode, ProcessDataAddDTO processDataAddDTO) throws XbbException {
        boolean result = false;
        boolean elseResult = false;
        PaasProcessTemplateNodeEntityExt elseProcessCondition = new PaasProcessTemplateNodeEntityExt();
        PaasProcessTemplateNodeEntityExt processCondition = new PaasProcessTemplateNodeEntityExt();
        UserEntity userEntity = userModel.getByKey(processDataAddDTO.getCreatorId(), processDataAddDTO.getCorpid());
        for (PaasProcessTemplateNodeEntityExt item : nextConditionNode) {
            processCondition = item;
            // else 条件
            if (Objects.equals(item.getConditionType(),2)) {
                elseResult = true;
                elseProcessCondition = item;
                continue;
            }
            // 流转条件为空，且不为结束节点
            boolean conditionIsEmpty = item.getConditions() == null || item.getConditions().isEmpty();
            if (conditionIsEmpty) {
                // 当条件为null时，直接生成下一条任务
                result = true;
                break;
            } else {
                List<ConditionsEntityExt> itemConditions = item.getConditions();
                for (ConditionsEntityExt condition : itemConditions) {
                    String conditionAttr = condition.getAttr();
                    Object value;
                    if (Objects.equals(conditionAttr, FieldTypeEnum.SERIALNO.getAlias())) {
                        value = processDataAddDTO.getSerialNo();
                    } else if (Objects.equals(conditionAttr, FieldTypeEnum.DEPARTMENTID.getAlias())) {
                        value = processDataAddDTO.getDepartmentId();
                    } else if (Objects.equals(conditionAttr, FieldTypeEnum.UPDATETIME.getAlias())) {
                        value = DateTimeUtil.getInt();
                    } else if (Objects.equals(conditionAttr, FieldTypeEnum.ADDTIME.getAlias())) {
                        value = DateTimeUtil.getInt();
                    } else if (Objects.equals(conditionAttr, FieldTypeEnum.CREATORID.getAlias())) {
                        value = processDataAddDTO.getCreatorId();
                    } else {
                        value = processDataAddDTO.getData().get(condition.getAttr());
                    }
                    if (Objects.equals(conditionAttr, "creator_dept")) {
                        result = false;
                        if (userEntity != null) {
                            List<Object> conditionList = condition.getValue();
                            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                            StringBuilder depIdInRegexp = new StringBuilder();
                            for (int i = 0; i < conditionList.size(); i++) {
                                String router = Objects.toString(conditionList.get(i), "0");
                                if (StringUtil.isNotEmpty(router)) {
                                    depIdInRegexp.append("(\\|").append(router).append("\\|)");
                                    if (i != conditionList.size() - 1) {
                                        depIdInRegexp.append("|");
                                    }
                                }
                            }
                            param.put("del", 0);
                            param.put("corpid", processDataAddDTO.getCorpid());
                            /*
                             * 数据库内dep_id_router字段的数值格式为：|1|2|4|
                             * 如果想获取部门id为1、2的部门的所有子部门，则等于获取dep_id_router所有包含"|1|"或"|2|"的
                             */
                            param.put("routerRegexp", depIdInRegexp.toString());
                            List<Long> perList = departmentModel.getDepIds(param);

                            String dept = userEntity.getDepartment();
                            JSONArray deptArray = JSON.parseArray(dept);
                            for (int i = 0; i < deptArray.size(); i++) {
                                Long router = deptArray.getLong(i);
                                if (perList.contains(router)) {
                                    result = true;
                                    break;
                                }
                            }
                        }
                    } else {
                        result = judgingCondition(condition, value);
                    }
                    if (!result) {
                        break;
                    }
                }
                if (result) {
                    break;
                }
            }
        }
        if (result) {
            // 满足条件，则生成任务
             return processCondition;
        } else if (elseResult) {
            // 当所有条件不满足，但是有else时，走此流程
            return elseProcessCondition;
        } else {
            // 所有条件不满足，则通过流程
            return null;
        }
    }

    private StartProcessVO createNodeTask(PaasProcessTemplateNodeEntityExt nextNode, ProcessDataAddDTO processDataAddDTO, Long lastNodeId) throws XbbException {
        StartProcessVO startProcessVO = new StartProcessVO();
        if (Objects.equals(nextNode.getType(), NodeTypeEnum.CC_PROCESS_NODE.getNodeType())) {
            // TODO 生成抄送任务
            List<OptionalRangeEntity> ccUserList = nextNode.getCcUserList();
            // 生成负责人任务
            if (!ccUserList.isEmpty()) {
                ProcessConditionValidDTO processConditionValidDTO = new ProcessConditionValidDTO();
                BeanUtil.copyProperties(processDataAddDTO, processConditionValidDTO);
                // 根据负责人生成任务
                List<ProcessNodeTaskAddDTO> ccUserNodeTaskList = nodeTaskListStartProcessService.getNodeTaskList(ccUserList, processConditionValidDTO, nextNode, TaskTypeEnum.CC.getType());
                if (!ccUserNodeTaskList.isEmpty()) {
                    ProcessNodeTaskAddBatchDTO processNodeTaskAddBatchDTO = new ProcessNodeTaskAddBatchDTO();
                    BeanUtil.copyProperties(processDataAddDTO, processNodeTaskAddBatchDTO);
                    processNodeTaskAddBatchDTO.setUserNodeTaskList(ccUserNodeTaskList);
                    processNodeTaskAddBatchDTO.setLastNodeId(lastNodeId);
                    processOperateHelp.createTask(processNodeTaskAddBatchDTO);
                }
            }
            startProcessVO = deliverToNextNode(nextNode, processDataAddDTO);
        } else if (Objects.equals(nextNode.getType(), NodeTypeEnum.PROCESS_NODE.getNodeType())) {
            // 系统自动通过
            boolean autoPaas = false;
            List<OptionalRangeEntity> userList = nextNode.getMainUserList();
            // 生成负责人任务
            ProcessConditionValidDTO processConditionValidDTO = new ProcessConditionValidDTO();
            BeanUtil.copyProperties(processDataAddDTO, processConditionValidDTO);
            List<ProcessNodeTaskAddDTO> userNodeTaskList = nodeTaskListStartProcessService.getNodeTaskList(userList, processConditionValidDTO, nextNode, TaskTypeEnum.UNTREATED.getType());
            if (!userNodeTaskList.isEmpty()) {
                // 审批人去重
                Integer removeUserNum = getProcessNodeTaskAddBatchDTO(nextNode, processDataAddDTO, lastNodeId, userNodeTaskList);
                ProcessNodeTaskAddBatchDTO processNodeTaskAddBatchDTO = new ProcessNodeTaskAddBatchDTO();
                BeanUtil.copyProperties(processDataAddDTO, processNodeTaskAddBatchDTO);
                processNodeTaskAddBatchDTO.setUserNodeTaskList(userNodeTaskList);
                processNodeTaskAddBatchDTO.setLastNodeId(lastNodeId);
                // processOperateHelp.createTask(processNodeTaskAddBatchDTO);
                // startProcessVO.setNoApprovalRequired(0);
                processOperateHelp.createTask(processNodeTaskAddBatchDTO);
                Integer signType = userNodeTaskList.get(0).getSignType();
                // 或签自动通过
                if (Objects.equals(signType, SignTypeEnum.ORSIGN.getValue()) && removeUserNum > 0) {
                    createCCTaskListAuto(nextNode, processDataAddDTO, lastNodeId, autoPaas, processConditionValidDTO);
                    // 修改审批状态
                    PaasProcessTaskEntity paasProcessTaskEntity = paasProcessTaskModel.getByKey(processDataAddDTO.getTaskId().intValue(), processDataAddDTO.getCorpid());
                    if (Objects.equals(paasProcessTaskEntity.getFlowStatus(), BasicConstant.ONE)) {
                        paasProcessTaskEntity.setFlowStatus(FlowStatusEnum.IN_APPROVAL.getType());
                        paasProcessTaskModel.update(paasProcessTaskEntity);
                    }
                    startProcessVO = deliverToNextNode(nextNode, processDataAddDTO);
                } else if (Objects.equals(signType, SignTypeEnum.COUNTERSIGN.getValue() )&& removeUserNum>0 && removeUserNum == userNodeTaskList.size()){
                    createCCTaskListAuto(nextNode, processDataAddDTO, lastNodeId, autoPaas, processConditionValidDTO);
                    // 修改审批状态
                    PaasProcessTaskEntity paasProcessTaskEntity = paasProcessTaskModel.getByKey(processDataAddDTO.getTaskId().intValue(), processDataAddDTO.getCorpid());
                    if (Objects.equals(paasProcessTaskEntity.getFlowStatus(), BasicConstant.ONE)) {
                        paasProcessTaskEntity.setFlowStatus(FlowStatusEnum.IN_APPROVAL.getType());
                        paasProcessTaskModel.update(paasProcessTaskEntity);
                    }
                    startProcessVO = deliverToNextNode(nextNode, processDataAddDTO);
                } else {
                    startProcessVO.setNoApprovalRequired(0);
                }
            } else {
                // 超管转交处理/自动通过/自动拒绝
                PaasProcessTemplateEntity processTemplateEntity = paasProcessTemplateModel.getByKey(nextNode.getTemplateId(), processDataAddDTO.getCorpid());
                Integer emptyApproverType = processTemplateEntity != null ? processTemplateEntity.getEmptyApproverType() : ProcessEmptyApproverTypeEnum.ADMIN_TRANSFER.getValue();

                ProcessNodeTaskAddDTO nodeTaskAddDTO = new ProcessNodeTaskAddDTO();
                BeanUtil.copyProperties(processConditionValidDTO, nodeTaskAddDTO);
                nodeTaskAddDTO.setTemplateNodeId(nextNode.getId());
                nodeTaskAddDTO.setNodeType(nextNode.getType());
                nodeTaskAddDTO.setUserId(PaasConstant.SYS_USER_ID);
                nodeTaskAddDTO.setTaskId(processConditionValidDTO.getTaskId());
                nodeTaskAddDTO.setSignType(SignTypeEnum.ORSIGN.getValue());
                nodeTaskAddDTO.setCreatorId(processDataAddDTO.getUserId());
                ProcessNodeTaskAddBatchDTO processNodeTaskAddBatchDTO = new ProcessNodeTaskAddBatchDTO();
                BeanUtil.copyProperties(processDataAddDTO, processNodeTaskAddBatchDTO);
                processNodeTaskAddBatchDTO.setLastNodeId(lastNodeId);

                // 自动通过
                if(Objects.equals(ProcessEmptyApproverTypeEnum.AUTO_PAAS.getValue(), emptyApproverType)) {
                    // 创建当前节点
                    nodeTaskAddDTO.setTaskType(TaskTypeEnum.COMMIT.getType());
                    userNodeTaskList.add(nodeTaskAddDTO);
                    getProcessNodeTaskAddBatchDTO(nextNode, processDataAddDTO, lastNodeId, userNodeTaskList);
                    processNodeTaskAddBatchDTO.setUserNodeTaskList(userNodeTaskList);
                    processOperateHelp.createTask(processNodeTaskAddBatchDTO);
                    startProcessVO = deliverToNextNode(nextNode, processDataAddDTO);
                    autoPaas = true;
                } else if(Objects.equals(ProcessEmptyApproverTypeEnum.AUTO_REJECT.getValue(), emptyApproverType)) {
                    nodeTaskAddDTO.setTaskType(TaskTypeEnum.END.getType());
                    userNodeTaskList.add(nodeTaskAddDTO);
                    processNodeTaskAddBatchDTO.setUserNodeTaskList(userNodeTaskList);
                    processOperateHelp.createTask(processNodeTaskAddBatchDTO);

                    startProcessVO.setNoApprovalRequired(2);
                } else {
                    // 超管转交处理
                    nodeTaskAddDTO.setTaskType(TaskTypeEnum.SYSTEM_COMMIT.getType());
                    userNodeTaskList.add(nodeTaskAddDTO);
                    processNodeTaskAddBatchDTO.setUserNodeTaskList(userNodeTaskList);
                    processOperateHelp.createTask(processNodeTaskAddBatchDTO);

                    startProcessVO.setNoApprovalRequired(0);
                }
            }
            // 生成抄送人任务
            List<OptionalRangeEntity> ccUserList = nextNode.getCcUserList();
            if (Objects.equals(nextNode.getEnableCCFlag(), 1) && !ccUserList.isEmpty()) {
                // 抄送人状态：区分系统自动通过
                Integer taskType = autoPaas ? TaskTypeEnum.CC.getType() : TaskTypeEnum.WAIT_CC.getType();
                // 根据负责人生成任务
                List<ProcessNodeTaskAddDTO> ccUserNodeTaskList = nodeTaskListStartProcessService.getNodeTaskList(ccUserList, processConditionValidDTO, nextNode, taskType);
                if (!ccUserNodeTaskList.isEmpty()) {
                    ProcessNodeTaskAddBatchDTO processNodeTaskAddBatchDTO = new ProcessNodeTaskAddBatchDTO();
                    BeanUtil.copyProperties(processDataAddDTO, processNodeTaskAddBatchDTO);
                    processNodeTaskAddBatchDTO.setUserNodeTaskList(ccUserNodeTaskList);
                    processNodeTaskAddBatchDTO.setLastNodeId(lastNodeId);
                    processOperateHelp.createTask(processNodeTaskAddBatchDTO);
                }
            }
        }
        return startProcessVO;
    }

    /**
     * 审批节点内设置抄送人 特殊处理
     * @param nextNode
     * @param processDataAddDTO
     * @param lastNodeId
     * @param autoPaas
     * @param processConditionValidDTO
     * @throws XbbException
     */
    private void createCCTaskListAuto(PaasProcessTemplateNodeEntityExt nextNode, ProcessDataAddDTO processDataAddDTO, Long lastNodeId, boolean autoPaas, ProcessConditionValidDTO processConditionValidDTO) throws XbbException {
        // 生成抄送人任务
        List<OptionalRangeEntity> ccUserList = nextNode.getCcUserList();
        if (Objects.equals(nextNode.getEnableCCFlag(), 1) && !ccUserList.isEmpty()) {
            // 抄送人状态：区分系统自动通过
            Integer taskType = autoPaas ? TaskTypeEnum.CC.getType() : TaskTypeEnum.WAIT_CC.getType();
            // 根据负责人生成任务
            List<ProcessNodeTaskAddDTO> ccUserNodeTaskList = nodeTaskListStartProcessService.getNodeTaskList(ccUserList, processConditionValidDTO, nextNode, taskType);
            for (ProcessNodeTaskAddDTO processNodeTaskAddDTO : ccUserNodeTaskList) {
                processNodeTaskAddDTO.setTaskType(TaskTypeEnum.CC.getType());
            }
            if (!ccUserNodeTaskList.isEmpty()) {
                ProcessNodeTaskAddBatchDTO processNodeTaskCCDTO = new ProcessNodeTaskAddBatchDTO();
                BeanUtil.copyProperties(processDataAddDTO, processNodeTaskCCDTO);
                processNodeTaskCCDTO.setUserNodeTaskList(ccUserNodeTaskList);
                processNodeTaskCCDTO.setLastNodeId(lastNodeId);
                processOperateHelp.createTask(processNodeTaskCCDTO);
            }
        }
    }

    private Integer getProcessNodeTaskAddBatchDTO(PaasProcessTemplateNodeEntityExt nextNode, ProcessDataAddDTO processDataAddDTO, Long lastNodeId, List<ProcessNodeTaskAddDTO> userNodeTaskList) {
        PaasProcessTemplateEntity processTemplateEntity = paasProcessTemplateModel.getByKey(nextNode.getTemplateId(), processDataAddDTO.getCorpid());
        // 查找审批记录
        HashMap<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid", processDataAddDTO.getCorpid());
        param.put("appId", processDataAddDTO.getAppId());
        param.put("menuId", processDataAddDTO.getMenuId());
        param.put("formId", processDataAddDTO.getFormId());
        param.put("taskId", processDataAddDTO.getTaskId());
        param.put("del", DelEnum.NORMAL.getDel());
        param.put("orderByStr", "update_time " + SortOrder.ASC + ", id " + SortOrder.ASC);
        List<PaasProcessNodeTaskEntityExt> nodeTaskList = paasProcessNodeTaskModel.findEntitys(param);
        LinkedHashMap<Long, List<String>> nodeTaskUser = new LinkedHashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Long templateNodeId = 0L;
        PaasProcessNodeTaskEntityExt createNodeTask = new PaasProcessNodeTaskEntityExt();
        for (PaasProcessNodeTaskEntityExt item : nodeTaskList) {
            if (getCreateNodeTask(item)) {
                // 这里的任务是重新提交的开始节点
                createNodeTask = item;
            }
        }
        List<String> approverIds = new ArrayList<>();
        for (PaasProcessNodeTaskEntityExt paasProcessNodeTaskEntityExt : nodeTaskList) {
            if (isApproverUser(lastNodeId, paasProcessNodeTaskEntityExt)) {
                if (createNodeTask.getAddTime() != null && createNodeTask.getAddTime() > paasProcessNodeTaskEntityExt.getAddTime()){
                    // 历史审批记录不做处理
                }else{
                    approverIds.add(paasProcessNodeTaskEntityExt.getUserId());
                    List<String> nodeTaskEntityExtList = nodeTaskUser.get(paasProcessNodeTaskEntityExt.getTemplateNodeId());
                    if (CollectionsUtil.isEmpty(nodeTaskEntityExtList)) {
                        nodeTaskEntityExtList = new ArrayList<>();
                    }
                    nodeTaskEntityExtList.add(paasProcessNodeTaskEntityExt.getUserId());
                    nodeTaskUser.put(paasProcessNodeTaskEntityExt.getTemplateNodeId(), nodeTaskEntityExtList);
                    templateNodeId = paasProcessNodeTaskEntityExt.getTemplateNodeId();
                }

            }
        }
        // 获取最近审批节点的审批人
        List<String> lastNodeTaskIdList = nodeTaskUser.get(templateNodeId);
        String createId = createNodeTask.getUserId();
        List<String> userIds = new ArrayList<>();
        userNodeTaskList.forEach(item -> {
            userIds.add(item.getUserId());
        });
        // 需要自动通过的审批人id
        List<String> needApproverDedup = new ArrayList<>();
        Boolean flag = false;
        if (Objects.equals(processTemplateEntity.getAutomaticallyApprovedSponsor(), BasicConstant.ONE)) {
            if (userIds.contains(createId)) {
                needApproverDedup.add(createId);
                flag =true;
            }
        }
        if (Objects.equals(processTemplateEntity.getApproverDeduplication(), ApproverDeduplicationEnum.APPROVERS_CONTINUOUSLY_DEDUPLICATION.getFlag()) && CollectionsUtil.isNotEmpty(lastNodeTaskIdList)) {
            // 同一个审批人连续出现,自动去重
            // if (userIds.contains(approverIds.get(approverIds.size() - 1))){
            //     // 自动去重
            //     needApproverDedup.add(approverIds.get(approverIds.size() - 1));
            //     flag =true;
            // }
            userIds.retainAll(lastNodeTaskIdList);
            if (CollectionsUtil.isNotEmpty(userIds)){
                needApproverDedup.addAll(userIds);
                flag=true;
            }

        } else if (Objects.equals(processTemplateEntity.getApproverDeduplication(), ApproverDeduplicationEnum.SAVE_FIRST_APPROVER.getFlag())) {
            // 同一个审批人多次出现,仅保留第一次
            // 判断两个列表是否包含对方的元素
            for (String userId : userIds) {
                if (approverIds.contains(userId)){
                    needApproverDedup.add(userId);
                    flag =true;
                }
            }
        }
        Integer signType = userNodeTaskList.get(0).getSignType();
        // 修改或签时task-type 为其他人审批
        Boolean once = true;
        Integer num =0;
        if (flag){
            for (ProcessNodeTaskAddDTO item : userNodeTaskList) {
                if (needApproverDedup.contains(item.getUserId()) && once) {
                    item.setTaskType(TaskTypeEnum.SYSTEM_PASS.getType());
                    num++;
                    // 防止多次重复出现会签
                    if ((Objects.equals(num,needApproverDedup.size()) && Objects.equals(signType, SignTypeEnum.COUNTERSIGN.getValue())) || (num == 1 && Objects.equals(signType, SignTypeEnum.ORSIGN.getValue())) ) {
                        once = false;
                    }
                    continue;
                }
                if (Objects.equals(signType, SignTypeEnum.ORSIGN.getValue())) {
                    item.setTaskType(TaskTypeEnum.OTHER_COMMIT.getType());
                }
            }
        }
        return num;
    }

    /**
     * 判断是不是审批开始节点
     * @param item
     * @return
     */
    private boolean getCreateNodeTask(PaasProcessNodeTaskEntityExt item) {
        return (item.getTaskType().equals(TaskTypeEnum.COMMIT.getType()) || item.getTaskType().equals(TaskTypeEnum.REVOKE.getType())) && NodeTypeEnum.START_PROCESS_NODE.getNodeType().equals(item.getNodeType());
    }

    /**
     * 判断是不是通过节点,系统自动通过
     * @param lastNodeId
     * @param item
     * @return
     */
    private boolean isApproverUser(Long lastNodeId, PaasProcessNodeTaskEntityExt item) {
        //判断是不是通过接地那,系统自动通过
        return (Objects.equals(item.getTaskType(), TaskTypeEnum.COMMIT.getType()) || Objects.equals(item.getTaskType(), TaskTypeEnum.SYSTEM_PASS.getType()))
                // 判断是不是开始节点
                && Objects.equals(item.getNodeType(), NodeTypeEnum.PROCESS_NODE.getNodeType());
    }

    /**
     * 发送钉钉待办消息
     * @author xingxing.xiao
     * @date 2019/12/23 20:06
     */
    private void sendDingtalkWorkrecord(StartProcessDTO startProcessDTO, Long taskId, Long nodeTaskId) throws XbbException {
        LOG.warn("创建钉钉待办实例,开始处理数据,公司id:"+startProcessDTO.getCorpid());
        // 获取 dingtalkProcessCode
        String dingtalkProcessCode = workflowDingtalkService.getDingtalkProcessCode(startProcessDTO.getCorpid());
        if (StringUtil.isNotEmpty(dingtalkProcessCode)) {
            String corpid = startProcessDTO.getCorpid();
            Long formId = startProcessDTO.getFormId();
            Integer saasMark = startProcessDTO.getSaasMark();

            // 表单名称
            String formName;
            // 内容提要
            String customTitle;
            List<FieldAttrEntity> explainList;
            if (Objects.equals(startProcessDTO.getBusinessType(), XbbRefTypeEnum.WORK_ORDER.getCode())) {
                WorkOrderFormEntity workOrderFormEntity = workOrderFormModel.getByKey(startProcessDTO.getFormId(), startProcessDTO.getCorpid());
                if (workOrderFormEntity == null) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_EXIST);
                }
                formName = workOrderFormEntity.getName();
                customTitle = workOrderFormEntity.getCustomTitle();
                WorkOrderExplainEntity workOrderExplainEntity = workOrderExplainModel.getByFormId(formId, corpid);
                if (Objects.isNull(workOrderExplainEntity)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
                }
                explainList = JSONArray.parseArray(workOrderExplainEntity.getExplains(), FieldAttrEntity.class);
            } else {
                PaasFormEntityExt paasFormEntityExt = paasFormModel.getByKey(startProcessDTO.getFormId(), startProcessDTO.getCorpid());
                if (paasFormEntityExt == null) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_EXIST);
                }
                formName = paasFormEntityExt.getName();
                customTitle = paasFormEntityExt.getCustomTitle();

                PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(formId, corpid);
                if (Objects.isNull(paasFormExplainEntity)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
                }
                explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
            }
            JSONArray titleArray = JSONArray.parseArray(customTitle);
            JSONArray attrArray = new JSONArray();
            for (Object obj : titleArray) {
                JSONObject attrJson = (JSONObject) obj;
                String attr = attrJson.getString("attr");
                attrArray.add(attr);
            }
            Map<String, FieldAttrEntity> explainMap = new HashMap<>(explainList.size());
            if(CollectionsUtil.isNotEmpty(explainList)){
                for(FieldAttrEntity fieldAttrEntity : explainList) {
                    if (attrArray.contains(fieldAttrEntity.getAttr())) {
                        explainMap.put(fieldAttrEntity.getAttr(), fieldAttrEntity);
                    }
                }
            }

            // 此处因为复用getDataList()和getSpecialDataList()方法，所以新建一个PaasFormDataEntityExt对象(不要去查询实体，因为还在审批中，查不到)，该对象目前用了addTime,updateTime,serialNo三个值
            PaasFormDataEntityExt paasFormDataEntityExt = new PaasFormDataEntityExt();
            // 还是做一遍查询吧
            PaasProcessDataEntity processData = paasProcessDataModel.getByTaskId(taskId, corpid);
            BeanUtil.copyProperties(processData, paasFormDataEntityExt);
            // data 要进行处理，不然复用 ExplainUtil 中的方法会报错 (此处坑很多，目前只能遇一个改一个)
            // 对数据进行深拷贝，不可使用源data，否则会有影响
            JSONObject data = (JSONObject) CloneUtil.deepClone(startProcessDTO.getData());
            // ownerId , coUserId, createId
            List<String> userIdList = new ArrayList<>();
            JSONArray ownerId = data.getJSONArray("ownerId");
            if (data.containsKey(FieldTypeEnum.OWNERID.getAlias()) && Objects.nonNull(ownerId)) {
                List<String> ownerIds = ownerId.toJavaList(String.class);
                userIdList.addAll(ownerIds);
            }
            JSONArray coUserId = data.getJSONArray("coUserId");
            if (data.containsKey(FieldTypeEnum.COUSERID.getAlias()) && Objects.nonNull(coUserId)) {
                List<String> coUserIds = coUserId.toJavaList(String.class);
                userIdList.addAll(coUserIds);
            }
            userIdList.add(processData.getCreatorId());
            List<UserEntity> userEntities = userModel.getByUserIdIn(corpid, userIdList, false);
            Map<String, UserEntity> userMap = new HashMap<>(userEntities.size());
            for (UserEntity userEntity : userEntities) {
                userMap.put(userEntity.getUserId(), userEntity);
            }

            // 解析标题
            List<FormTitlePoJo> formTitleList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if (Objects.equals(saasMark, SaasMarkEnum.SAAS.getCode())) {
                if (data.containsKey(FieldTypeEnum.OWNERID.getAlias()) && Objects.nonNull(ownerId)) {
                    List<ReturnUserAndDepartmentPojo> pojoList = new ArrayList<>();
                    for (Object o : ownerId) {

                        UserEntity userEntity = userMap.get(o.toString());
                        if(userEntity==null){
                            continue;
                        }
                        ReturnUserAndDepartmentPojo returnUserAndDepartmentPojo = new ReturnUserAndDepartmentPojo(userEntity.getUserId(), userEntity.getName());
                        pojoList.add(returnUserAndDepartmentPojo);
                    }
                    data.put(FieldTypeEnum.OWNERID.getAlias(), pojoList);
                }
                if (data.containsKey(FieldTypeEnum.COUSERID.getAlias()) && Objects.nonNull(coUserId)) {
                    List<ReturnUserAndDepartmentPojo> pojoList = new ArrayList<>();
                    for (Object o : coUserId) {
                        UserEntity userEntity = userMap.get(o.toString());
                        if(userEntity==null){
                            continue;
                        }
                        ReturnUserAndDepartmentPojo returnUserAndDepartmentPojo = new ReturnUserAndDepartmentPojo(userEntity.getUserId(), userEntity.getName());
                        pojoList.add(returnUserAndDepartmentPojo);
                    }
                    data.put(FieldTypeEnum.COUSERID.getAlias(), pojoList);
                }
                // 创建人
                data.put(FieldTypeEnum.CREATORID.getAlias(),  userMap.get(processData.getCreatorId()).getName());
                formTitleList = ExplainUtil.getSpecailFormTitle(titleArray, explainMap, data, explainList, paasFormDataEntityExt);
            } else if (Objects.equals(saasMark, SaasMarkEnum.PAAS.getCode())) {
                if (data.containsKey(FieldTypeEnum.OWNERID.getAlias())) {
                    JSONArray jsonArray = data.getJSONArray(FieldTypeEnum.OWNERID.getAlias());
                    if (Objects.nonNull(jsonArray) && !jsonArray.isEmpty()) {
                        data.put(FieldTypeEnum.OWNERID.getAlias(), userMap.get(data.getJSONArray("ownerId").get(0).toString()).getName());
                    }
                }
                data.put(FieldTypeEnum.CREATORID.getAlias(), userMap.get(processData.getCreatorId()).getName());
                // 48627 【紧急】【KA大客户】自定义表单进入审批后下拉框字段在钉钉待办中显示乱码
                try {
                    explainMap.values().forEach(fieldAttrEntity -> {
                        if (Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.COMBO.getType())) {
                            String comboCode = data.getString(fieldAttrEntity.getAttr());
                            ItemPoJo itemPoJo = fieldAttrEntity.getItems().stream().filter(item -> Objects.equals(item.getValue(), comboCode)).findFirst().orElse(null);
                            if (Objects.nonNull(itemPoJo)) {
                                data.put(fieldAttrEntity.getAttr(), itemPoJo.getText());
                            }
                        }
                    });
                } catch (Exception e) {
                    LOG.error("同步到钉钉待办的时候Paas表单数据解析错误", e);
                }
                formTitleList = ExplainUtil.getFormTitle(titleArray, explainMap, data, explainList, paasFormDataEntityExt);
            }
            // 拼接summaryTitle
            StringBuilder summaryTitle = new StringBuilder();
            for (FormTitlePoJo item : formTitleList) {
                if (StringUtil.isEmpty(item.getAttr())) {
                    summaryTitle.append(item.getContent()).append(" ");
                } else {
                    for (Object object : item.getValue()) {
                        summaryTitle.append(object.toString()).append(" ");
                    }
                }
            }
            // 复用OA消息的 options
            PushRefTypePojo.Options options = new PushRefTypePojo.Options(startProcessDTO.getAppId(), startProcessDTO.getMenuId(), startProcessDTO.getFormId(), null,
                    startProcessDTO.getSaasMark(), startProcessDTO.getBusinessType(), taskId, nodeTaskId, ProcessTypeEnum.CREATE.getValue());
            // formName: 表单名称， userId：表单提交人id， userName:表单提交人姓名， submitTime: 提交时间 options：复用OA消息的 options
            UserEntity creatorUser = userModel.getByKeyIngoreDel(startProcessDTO.getCreatorId(), corpid);
            LOG.warn("创建钉钉待办实例,结束处理数据,公司id:"+startProcessDTO.getCorpid());
            // 防空指针
            if (Objects.nonNull(creatorUser)){
                WorkrecordInstanceDTO workrecordInstanceDTO = new WorkrecordInstanceDTO(corpid, dingtalkProcessCode, formName, summaryTitle.toString(), startProcessDTO.getCreatorId(), creatorUser.getName(), DateUtil.getInt(), options);
                workflowDingtalkService.createDingtalkInstance(workrecordInstanceDTO);
            }
        }
    }

    private boolean judgingCondition(ConditionsEntityExt condition, Object value) throws XbbException {
        boolean result;
        try {
            result = compareValueByConditionHelp.compareValueByCondition(condition, value);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("PaasProcessCondition.judgingCondition数据库流转条件判断操作出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return result;
    }

    /**
     * 保存流程富文本
     *
     * @param processDataAddDTO
     * @param richTextData
     */
    private void saveProcessRichText(ProcessDataAddDTO processDataAddDTO, Object richTextData) {
        if (Objects.isNull(richTextData)) {
            return;
        }
        PaasProcessRichTextEntity entity = new PaasProcessRichTextEntity();
        BeanUtil.copyProperties(processDataAddDTO, entity);
        entity.setDistributorMark(Optional.ofNullable(entity.getDistributorMark()).orElse(BasicConstant.ZERO));
        Long now = DateTimeUtil.getInt();
        entity.setAddTime(now);
        entity.setUpdateTime(now);
        entity.setData(richTextData.toString());
        paasProcessRichTextModel.insert(entity);
    }
}
